/**
 * @(#) DatabaseMetaDataUtils.java
 *
 * @author lihg
 * @version V1.0 2013-11-11
 *
 */

package cn.com.dshome.database.jdbc;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import cn.com.dshome.database.jdbc.pojo.ColumnInformation;
import cn.com.dshome.database.jdbc.pojo.DBInformation;
import cn.com.dshome.database.jdbc.pojo.TableInformation;

/**
 * 
 * Purpose:获取数据库的信息
 * 
 * @author lihg
 * @see
 * @since
 */

@Component("databaseMetaData")
public class DatabaseMetaDataUtils {
	private static Logger log = Logger.getLogger(DatabaseMetaDataUtils.class);
	@Autowired
	private DBConnection dbConnection ;

	private DatabaseMetaData dbmd ;

	private String catalog ;

	public DatabaseMetaDataUtils() {
		if(null == dbConnection) {
			dbConnection = new DBConnection() ;
		}
		dbmd = getDbmd() ;
	}

	/**返回DatabaseMetaData
	 * @return the dbmd
	 */
	public DatabaseMetaData getDbmd() {
		if(null == dbmd) {
			try {
				Connection connection = dbConnection.getConnection() ;
				catalog = connection.getCatalog() ;
				dbmd = connection.getMetaData() ;
			} catch (Exception e) {
				DatabaseMetaDataUtils.log.error("获取DatabaseMetaData失败",e) ;
			}
		}
		return dbmd;
	}

	/**
	 * 获取数据库基本信息
	 * @author lihg
	 * @version V1.0 2013-11-11
	 * @return
	 */
	public DBInformation getDBInformation() {
		DBInformation dbInformation = new DBInformation() ;
		try {
			dbInformation.setDbProductName(dbmd.getDatabaseProductName()) ;
			dbInformation.setDbProductVersion(dbmd.getDatabaseProductVersion()) ;
			dbInformation.setDriverName(dbmd.getDriverName()) ;
			dbInformation.setDriverVersion(dbmd.getDriverVersion()) ;
			dbInformation.setReadOnly(dbmd.isReadOnly()) ;
			dbInformation.setUrl(dbmd.getURL()) ;
			dbInformation.setUser(dbmd.getUserName()) ;
			dbInformation.setCatalog(catalog) ;
			//			dbInformation.setSchema(dbmd.getConnection().get)
			DatabaseMetaDataUtils.log.info(dbInformation) ;
			//只取当前用户表
			dbInformation.setTables(getTableInformations(catalog,dbInformation.getUser(),"TABLE","VIEW")) ;
		} catch (SQLException e) {
			DatabaseMetaDataUtils.log.error("获取数据库基本信息失败",e) ;
		}
		return dbInformation ;
	}

	/**
	 * 获取表或视图列表信息
	 * @author lihg
	 * @version V1.0 2013-11-11
	 * @param catalog
	 * @param schema
	 * @param tableTypes 表类型 典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
	 * @return
	 */
	public Set<TableInformation> getTableInformations(String catalog,String schema,String ...tableTypes){
		Set<TableInformation> tables = new LinkedHashSet<TableInformation>() ;
		ResultSet rs = null ;
		try {
			rs = dbmd.getTables(catalog, schema, "%", tableTypes) ;
			while(rs.next()) {
				TableInformation tableInformation = new TableInformation() ;
				tableInformation.setName(rs.getString("TABLE_NAME")) ;
				tableInformation.setType(rs.getString("TABLE_TYPE")) ;
				tableInformation.setRemark(rs.getString("REMARKS")) ;
				tableInformation.setCatalog(catalog) ;
				tableInformation.setSchema(schema) ;
				DatabaseMetaDataUtils.log.info(tableInformation) ;
				tableInformation.setColumnSet(getColumnInformations(catalog,schema,tableInformation.getName())) ;
				tables.add(tableInformation) ;
			}
		} catch (SQLException e) {
			DatabaseMetaDataUtils.log.error("获取数据库表基本信息失败",e) ;
		}finally {
			if(null != rs) {
				try {
					rs.close() ;
				} catch (SQLException e) {
					DatabaseMetaDataUtils.log.error("关闭表基本信息连接失败",e) ;
				}
			}
		}
		return tables ;
	}


	/**
	 * 获取字段信息
	 * @author lihg
	 * @version V1.0 2013-11-11
	 * @param catalog
	 * @param schema
	 * @param tableName 要取字段的表名
	 * @return
	 */
	public Set<ColumnInformation> getColumnInformations(String catalog,String schema,String tableName){

		Set<ColumnInformation> columns = new LinkedHashSet<ColumnInformation>() ;
		ResultSet rs = null ;
		try {
			rs = dbmd.getColumns(catalog, schema, tableName, "%") ;
			while(rs.next()) {
				ColumnInformation columnInformation = new ColumnInformation() ;
				columnInformation.setName(rs.getString("COLUMN_NAME")) ;
				columnInformation.setDataType(rs.getInt("DATA_TYPE")) ;
				columnInformation.setDataTypeName(rs.getString("TYPE_NAME")) ;
				columnInformation.setColumnSize(rs.getInt("COLUMN_SIZE")) ;
				columnInformation.setDecimalDigits(rs.getInt("DECIMAL_DIGITS")) ;
				columnInformation.setNumPrecRadix(rs.getInt("NUM_PREC_RADIX")) ;
				columnInformation.setNullAble(rs.getInt("NULLABLE")) ;
				columnInformation.setRemark(rs.getString("REMARKS")) ;
				columnInformation.setColumnDef(rs.getString("COLUMN_DEF")) ;
				columnInformation.setCharOctetLength(rs.getInt("CHAR_OCTET_LENGTH")) ;
				columnInformation.setOrdinalPosition(rs.getInt("ORDINAL_POSITION")) ;
				columnInformation.setIsNullAble(rs.getString("IS_NULLABLE")) ;
				try {
					columnInformation.setIsAutoincrement(rs	.getString("IS_AUTOINCREMENT"));
				} catch (Exception e) {
				}
				columns.add(columnInformation) ;
			}
		} catch (SQLException e) {
			DatabaseMetaDataUtils.log.error("获取数据库表字段基本信息失败",e) ;
		}finally {
			if(null != rs) {
				try {
					rs.close() ;
				} catch (SQLException e) {
					DatabaseMetaDataUtils.log.error("关闭字段基本信息连接失败",e) ;
				}
			}
		}
		return columns ;
	}
}


/**
 * Revision history
 * -------------------------------------------------------------------------
 * 
 * Date Author Note
 * -------------------------------------------------------------------------
 * 2013-11-11上午11:49:24 lihg 创建版本
 */